package com.lineage.server.world;

import com.lineage.server.model.Instance.L1NpcInstance;
import com.lineage.server.model.L1Location;
import com.lineage.server.model.map.L1Map;
import com.lineage.server.types.Point;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class WorldNpc {
  private static final Log _log = LogFactory.getLog(WorldNpc.class);
  
  private static WorldNpc _instance;
  
  private final ConcurrentHashMap<Integer, L1NpcInstance> _isNpc;
  
  private Collection<L1NpcInstance> _allNpcValues;
  
  public static WorldNpc get() {
    if (_instance == null)
      _instance = new WorldNpc(); 
    return _instance;
  }
  
  private WorldNpc() {
    this._isNpc = new ConcurrentHashMap<>();
  }
  
  public Collection<L1NpcInstance> all() {
    try {
      Collection<L1NpcInstance> vs = this._allNpcValues;
      return (vs != null) ? vs : (this._allNpcValues = Collections.unmodifiableCollection(this._isNpc.values()));
    } catch (Exception e) {
      _log.error(e.getLocalizedMessage(), e);
      return null;
    } 
  }
  
  public ConcurrentHashMap<Integer, L1NpcInstance> map() {
    return this._isNpc;
  }
  
  public void put(Integer key, L1NpcInstance value) {
    try {
      this._isNpc.put(key, value);
    } catch (Exception e) {
      _log.error(e.getLocalizedMessage(), e);
    } 
  }
  
  public void remove(Integer key) {
    try {
      this._isNpc.remove(key);
    } catch (Exception e) {
      _log.error(e.getLocalizedMessage(), e);
    } 
  }
  
  public ArrayList<L1NpcInstance> getVisibleMob(L1NpcInstance src) {
    L1Map map = src.getMap();
    L1Location l1Location = src.getLocation();
    ArrayList<L1NpcInstance> result = new ArrayList<>();
    Iterator<L1NpcInstance> iter = all().iterator();
    while (iter.hasNext()) {
      L1NpcInstance element = iter.next();
      if (element.equals(src))
        continue; 
      if (map != element.getMap())
        continue; 
      if (!l1Location.isInScreen((Point)element.getLocation()))
        continue; 
      result.add(element);
    } 
    return result;
  }
  
  public int getVisibleCount(L1NpcInstance src) {
    L1Map map = src.getMap();
    L1Location l1Location = src.getLocation();
    int count = 0;
    Iterator<L1NpcInstance> iter = all().iterator();
    while (iter.hasNext()) {
      L1NpcInstance element = iter.next();
      if (element.equals(src))
        continue; 
      if (map != element.getMap())
        continue; 
      if (!l1Location.isInScreen((Point)element.getLocation()) || src.getNpcId() != element.getNpcId())
        continue; 
      count++;
    } 
    return count;
  }
}
